package org.example;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.fisco.bcos.sdk.abi.FunctionReturnDecoder;
import org.fisco.bcos.sdk.abi.TypeReference;
import org.fisco.bcos.sdk.abi.datatypes.DynamicStruct;
import org.fisco.bcos.sdk.abi.datatypes.Function;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.Utf8String;
import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple1;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple2;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple3;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.contract.Contract;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;

@SuppressWarnings("unchecked")
public class TimeCurrency extends Contract {
    public static final String[] BINARY_ARRAY = {"608060405234801561001057600080fd5b50610961806100206000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806331feb6711461005c5780635728b97314610099578063585e73aa146100c2575b600080fd5b34801561006857600080fd5b50610083600480360361007e9190810190610629565b6100ff565b604051610090919061082f565b60405180910390f35b3480156100a557600080fd5b506100c060048036036100bb919081019061066a565b610230565b005b3480156100ce57600080fd5b506100e960048036036100e491908101906106d6565b6102eb565b6040516100f6919061080d565b60405180910390f35b610107610500565b6000826040518082805190602001908083835b60208310151561013f578051825260208201915060208101905060208303925061011a565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020604080519081016040529081600082018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102165780601f106101eb57610100808354040283529160200191610216565b820191906000526020600020905b8154815290600101906020018083116101f957829003601f168201915b505050505081526020016001820154815250509050919050565b610238610500565b604080519081016040528083815260200160648152509050806000846040518082805190602001908083835b6020831015156102895780518252602082019150602081019050602083039250610264565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008201518160000190805190602001906102d892919061051a565b5060208201518160010155905050505050565b6060816000856040518082805190602001908083835b6020831015156103265780518252602082019150602081019050602083039250610301565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390206001015410151561049957816000856040518082805190602001908083835b60208310151561039d5780518252602082019150602081019050602083039250610378565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060010160008282540392505081905550816000846040518082805190602001908083835b60208310151561041957805182526020820191506020810190506020830392506103f4565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020600101600082825401925050819055506040805190810160405280600c81526020017fe8bdace8b4a6e68890e58a9f000000000000000000000000000000000000000081525090506104f9565b606060405190810160405280602481526020017fe8bdace8b4a6e5a4b1e8b4a5efbc8ce8afb7e69fa5e79c8be8b4a6e688b7e4bd81526020017f99e9a29d0000000000000000000000000000000000000000000000000000000081525090505b9392505050565b604080519081016040528060608152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061055b57805160ff1916838001178555610589565b82800160010185558215610589579182015b8281111561058857825182559160200191906001019061056d565b5b509050610596919061059a565b5090565b6105bc91905b808211156105b85760008160009055506001016105a0565b5090565b90565b600082601f83011215156105d257600080fd5b81356105e56105e08261087e565b610851565b9150808252602083016020830185838301111561060157600080fd5b61060c8382846108d4565b50505092915050565b600061062182356108ca565b905092915050565b60006020828403121561063b57600080fd5b600082013567ffffffffffffffff81111561065557600080fd5b610661848285016105bf565b91505092915050565b6000806040838503121561067d57600080fd5b600083013567ffffffffffffffff81111561069757600080fd5b6106a3858286016105bf565b925050602083013567ffffffffffffffff8111156106c057600080fd5b6106cc858286016105bf565b9150509250929050565b6000806000606084860312156106eb57600080fd5b600084013567ffffffffffffffff81111561070557600080fd5b610711868287016105bf565b935050602084013567ffffffffffffffff81111561072e57600080fd5b61073a868287016105bf565b925050604061074b86828701610615565b9150509250925092565b6000610760826108b5565b8084526107748160208601602086016108e3565b61077d81610916565b602085010191505092915050565b6000610796826108aa565b8084526107aa8160208601602086016108e3565b6107b381610916565b602085010191505092915050565b600060408301600083015184820360008601526107de828261078b565b91505060208301516107f360208601826107fe565b508091505092915050565b610807816108c0565b82525050565b600060208201905081810360008301526108278184610755565b905092915050565b6000602082019050818103600083015261084981846107c1565b905092915050565b6000604051905081810181811067ffffffffffffffff8211171561087457600080fd5b8060405250919050565b600067ffffffffffffffff82111561089557600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b600081519050919050565b6000819050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156109015780820151818401526020810190506108e6565b83811115610910576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a72305820cb2a0273e2ae34a7e66d93c0e9eead7d1303701c31530cf5bdf18cdfeef784ce6c6578706572696d656e74616cf50037"};

    public static final String BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", BINARY_ARRAY);

    public static final String[] SM_BINARY_ARRAY = {"608060405234801561001057600080fd5b50610961806100206000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806331feb6711461005c5780635728b97314610099578063585e73aa146100c2575b600080fd5b34801561006857600080fd5b50610083600480360361007e9190810190610629565b6100ff565b604051610090919061082f565b60405180910390f35b3480156100a557600080fd5b506100c060048036036100bb919081019061066a565b610230565b005b3480156100ce57600080fd5b506100e960048036036100e491908101906106d6565b6102eb565b6040516100f6919061080d565b60405180910390f35b610107610500565b6000826040518082805190602001908083835b60208310151561013f578051825260208201915060208101905060208303925061011a565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020604080519081016040529081600082018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102165780601f106101eb57610100808354040283529160200191610216565b820191906000526020600020905b8154815290600101906020018083116101f957829003601f168201915b505050505081526020016001820154815250509050919050565b610238610500565b604080519081016040528083815260200160648152509050806000846040518082805190602001908083835b6020831015156102895780518252602082019150602081019050602083039250610264565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060008201518160000190805190602001906102d892919061051a565b5060208201518160010155905050505050565b6060816000856040518082805190602001908083835b6020831015156103265780518252602082019150602081019050602083039250610301565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390206001015410151561049957816000856040518082805190602001908083835b60208310151561039d5780518252602082019150602081019050602083039250610378565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060010160008282540392505081905550816000846040518082805190602001908083835b60208310151561041957805182526020820191506020810190506020830392506103f4565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020600101600082825401925050819055506040805190810160405280600c81526020017fe8bdace8b4a6e68890e58a9f000000000000000000000000000000000000000081525090506104f9565b606060405190810160405280602481526020017fe8bdace8b4a6e5a4b1e8b4a5efbc8ce8afb7e69fa5e79c8be8b4a6e688b7e4bd81526020017f99e9a29d0000000000000000000000000000000000000000000000000000000081525090505b9392505050565b604080519081016040528060608152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061055b57805160ff1916838001178555610589565b82800160010185558215610589579182015b8281111561058857825182559160200191906001019061056d565b5b509050610596919061059a565b5090565b6105bc91905b808211156105b85760008160009055506001016105a0565b5090565b90565b600082601f83011215156105d257600080fd5b81356105e56105e08261087e565b610851565b9150808252602083016020830185838301111561060157600080fd5b61060c8382846108d4565b50505092915050565b600061062182356108ca565b905092915050565b60006020828403121561063b57600080fd5b600082013567ffffffffffffffff81111561065557600080fd5b610661848285016105bf565b91505092915050565b6000806040838503121561067d57600080fd5b600083013567ffffffffffffffff81111561069757600080fd5b6106a3858286016105bf565b925050602083013567ffffffffffffffff8111156106c057600080fd5b6106cc858286016105bf565b9150509250929050565b6000806000606084860312156106eb57600080fd5b600084013567ffffffffffffffff81111561070557600080fd5b610711868287016105bf565b935050602084013567ffffffffffffffff81111561072e57600080fd5b61073a868287016105bf565b925050604061074b86828701610615565b9150509250925092565b6000610760826108b5565b8084526107748160208601602086016108e3565b61077d81610916565b602085010191505092915050565b6000610796826108aa565b8084526107aa8160208601602086016108e3565b6107b381610916565b602085010191505092915050565b600060408301600083015184820360008601526107de828261078b565b91505060208301516107f360208601826107fe565b508091505092915050565b610807816108c0565b82525050565b600060208201905081810360008301526108278184610755565b905092915050565b6000602082019050818103600083015261084981846107c1565b905092915050565b6000604051905081810181811067ffffffffffffffff8211171561087457600080fd5b8060405250919050565b600067ffffffffffffffff82111561089557600080fd5b601f19601f8301169050602081019050919050565b600081519050919050565b600081519050919050565b6000819050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156109015780820151818401526020810190506108e6565b83811115610910576000848401525b50505050565b6000601f19601f83011690509190505600a265627a7a72305820cb2a0273e2ae34a7e66d93c0e9eead7d1303701c31530cf5bdf18cdfeef784ce6c6578706572696d656e74616cf50037"};

    public static final String SM_BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);

    public static final String[] ABI_ARRAY = {"[{\"methodSignatureAsString\":\"getUser(string)\",\"name\":\"getUser\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[{\"name\":\"_userId\",\"type\":\"string\",\"internalType\":\"\",\"indexed\":false,\"components\":[],\"dynamic\":true,\"typeAsString\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"\",\"indexed\":false,\"components\":[{\"name\":\"name\",\"type\":\"string\",\"internalType\":\"\",\"indexed\":false,\"components\":[],\"dynamic\":true,\"typeAsString\":\"string\"},{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"\",\"indexed\":false,\"components\":[],\"dynamic\":false,\"typeAsString\":\"uint256\"}],\"dynamic\":true,\"typeAsString\":\"(string,uint256)\"}]},{\"methodSignatureAsString\":\"setUser(string,string)\",\"name\":\"setUser\",\"type\":\"function\",\"constant\":false,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"nonpayable\",\"inputs\":[{\"name\":\"_userId\",\"type\":\"string\",\"internalType\":\"\",\"indexed\":false,\"components\":[],\"dynamic\":true,\"typeAsString\":\"string\"},{\"name\":\"_name\",\"type\":\"string\",\"internalType\":\"\",\"indexed\":false,\"components\":[],\"dynamic\":true,\"typeAsString\":\"string\"}],\"outputs\":[]},{\"methodSignatureAsString\":\"transition(string,string,uint256)\",\"name\":\"transition\",\"type\":\"function\",\"constant\":false,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"nonpayable\",\"inputs\":[{\"name\":\"_sendId\",\"type\":\"string\",\"internalType\":\"\",\"indexed\":false,\"components\":[],\"dynamic\":true,\"typeAsString\":\"string\"},{\"name\":\"_getId\",\"type\":\"string\",\"internalType\":\"\",\"indexed\":false,\"components\":[],\"dynamic\":true,\"typeAsString\":\"string\"},{\"name\":\"_money\",\"type\":\"uint256\",\"internalType\":\"\",\"indexed\":false,\"components\":[],\"dynamic\":false,\"typeAsString\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"\",\"indexed\":false,\"components\":[],\"dynamic\":true,\"typeAsString\":\"string\"}]}]"};

    public static final String ABI = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", ABI_ARRAY);

    public static final String FUNC_GETUSER = "getUser";

    public static final String FUNC_SETUSER = "setUser";

    public static final String FUNC_TRANSITION = "transition";

    protected TimeCurrency(String contractAddress, Client client, CryptoKeyPair credential) {
        super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    }

    public static String getBinary(CryptoSuite cryptoSuite) {
        return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    }

    public Struct0 getUser(String _userId) throws ContractException {
        final Function function = new Function(FUNC_GETUSER, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_userId)), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Struct0>() {}));
        return executeCallWithSingleValueReturn(function, Struct0.class);
    }

    public TransactionReceipt setUser(String _userId, String _name) {
        final Function function = new Function(
                FUNC_SETUSER, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_userId), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_name)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] setUser(String _userId, String _name, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_SETUSER, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_userId), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_name)), 
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForSetUser(String _userId, String _name) {
        final Function function = new Function(
                FUNC_SETUSER, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_userId), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_name)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple2<String, String> getSetUserInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_SETUSER, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple2<String, String>(

                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue()
                );
    }

    public TransactionReceipt transition(String _sendId, String _getId, BigInteger _money) {
        final Function function = new Function(
                FUNC_TRANSITION, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_sendId), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_getId), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(_money)), 
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] transition(String _sendId, String _getId, BigInteger _money, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_TRANSITION, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_sendId), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_getId), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(_money)), 
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForTransition(String _sendId, String _getId, BigInteger _money) {
        final Function function = new Function(
                FUNC_TRANSITION, 
                Arrays.<Type>asList(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_sendId), 
                new org.fisco.bcos.sdk.abi.datatypes.Utf8String(_getId), 
                new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(_money)), 
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple3<String, String, BigInteger> getTransitionInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_TRANSITION, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple3<String, String, BigInteger>(

                (String) results.get(0).getValue(), 
                (String) results.get(1).getValue(), 
                (BigInteger) results.get(2).getValue()
                );
    }

    public Tuple1<String> getTransitionOutput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getOutput();
        final Function function = new Function(FUNC_TRANSITION, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple1<String>(

                (String) results.get(0).getValue()
                );
    }

    public static TimeCurrency load(String contractAddress, Client client, CryptoKeyPair credential) {
        return new TimeCurrency(contractAddress, client, credential);
    }

    public static TimeCurrency deploy(Client client, CryptoKeyPair credential) throws ContractException {
        return deploy(TimeCurrency.class, client, credential, getBinary(client.getCryptoSuite()), "");
    }

    public static class Struct0 extends DynamicStruct {
        public String name;

        public BigInteger balance;

        public Struct0(Utf8String name, Uint256 balance) {
            super(name,balance);
            this.name = name.getValue();
            this.balance = balance.getValue();
        }

        public Struct0(String name, BigInteger balance) {
            super(new org.fisco.bcos.sdk.abi.datatypes.Utf8String(name),new org.fisco.bcos.sdk.abi.datatypes.generated.Uint256(balance));
            this.name = name;
            this.balance = balance;
        }
    }
}
